_Pragma("once");

#include <unordered_map>
#include <string>
#include<forward_list>
#include <vector>
#include <unistd.h>
#include <exception>

#include "SingletonTemplate.h"
#include "ExtendDevice.h"
#include "HalUtility.h"
#include "SerialPortCommunicator485.h"
#include "Workable.h"
#include "common.h"
#include "SerialPortCommunicator.h"
#include "MachineDependenceConst.h"


template<class T>
bool operator==(const std::weak_ptr<T>& left, const std::weak_ptr<T>& right) {
    return left.lock().get() == right.lock().get();

}

class ConfigManager;

class IExtendDeviceManager : public Workable<IExtendDeviceManager> {
public:
    using ChannelDevices = std::pair<ChannelUniquePtr, std::forward_list<ExtendDevicePtr>>;

    /** Default destructor */
    virtual ~IExtendDeviceManager();

    void initialize();

    void finish();

    /**
     * 拓展回路设备确认协议 如果没有设备则返回null
     *
     * @param extendNum
     *            查询指定的设备通道
     * @return 返回当前指定通道的设备
     */
    ssize_t findExtendDevice(ChannelDevices& channelDevices);


    ssize_t createAndAddExtendDevice(const std::string& checkDeviceInfo, ChannelDevices& channelDevices);

    virtual bool updateOnlineDevice(ChannelDevices& channelDevices) = 0;


    ExtendDeviceWeakPtrs& getExtendDevices(const ExtendDeviceType& deviceType) {
        return mtypeToExtendDevice[&deviceType];
    }

    const ExtendDeviceWeakPtr* getAllOnlineExtendDevices() {
        return mallOnlineDevice;
    }


    void updateInnerDevice() noexcept {
        for (ExtendDevicePtr& devicePtr : minnerDevices) {
            try {
                devicePtr->activeUpdateInformation();
            } catch (std::exception& ex) {
                LOG_ERROR("%s,%s,%s", __FILE__, __FUNCTION__, ex.what());
            }
        }
    }


    virtual bool initial() {
        mnewOnlineDevice.clear();
        for (int i = 1; i < MDConst::DEFAULT_CHANNEL_COUNT; ++i) {//
            findExtendDevice(channelDevicesArray[i]);
        }


        Task* pTask = &mrefreshTask;
        mpool->pushPool(pTask);

        return true;
    }

    virtual bool uninitial() {

        return true;
    }

    virtual bool doWork() = 0;


       ChannelDevices channelDevicesArray[MDConst::DEFAULT_CHANNEL_COUNT];
protected:

    /** Default constructor */
    IExtendDeviceManager(DeviceCommunicator& oCommunicator);

    void addDevice(ChannelDevices& channelDevices, ExtendDevice* pExtendDevice) {
        ExtendDevicePtr extendDevicePtr(pExtendDevice);

        channelDevices.second.emplace_front(extendDevicePtr);

        mnewOnlineDevice.emplace_back(extendDevicePtr);
        //   mtypeToExtendDevice[&pExtendDevice->mdeviceType].emplace_back(extendDevicePtr);
    }


    void addInnerDevice(ExtendDevice* pExtendDevice) {
        ExtendDevicePtr extendDevicePtr(pExtendDevice);

        minnerDevices.emplace_back(extendDevicePtr);

        mnewOnlineDevice.emplace_back(extendDevicePtr);
        //   mtypeToExtendDevice[&pExtendDevice->mdeviceType].emplace_back(extendDevicePtr);
    }

    void adjustDevice();

    SerialPortCommunicator innerCommunicator;
    DeviceCommunicator& outerCommunicator;

    std::unordered_map<const ExtendDeviceType*, ExtendDeviceWeakPtrs>  mtypeToExtendDevice;
//    ChannelDevices channelDevicesArray[MDConst::DEFAULT_CHANNEL_COUNT];
    ExtendDeviceWeakPtr mallOnlineDevice[MDConst::DEFAULT_CHANNEL_COUNT];

    std::vector<ExtendDevicePtr> minnerDevices;

    std::vector<ExtendDevicePtr> mnewOnlineDevice;

    //callback for main thread
    ObjectFunction mrefreshFunction;
    Task mrefreshTask;
    WorkerBase::PoolType* const mpool;

    ConfigManager& mconfigManager;
};


